package com.geodroid.common.kernel.algos;


import com.geodroid.common.kernel.geos.ConstructionElement;
import com.geodroid.common.kernel.geos.GeoElement;

public abstract class AlgoElement extends ConstructionElement {

	/** input elements*/
	public GeoElement[] input;
	private GeoElement[] output;
	
	abstract protected void compute();

	protected void doSetDependencies() {
//		setRandomUnlabeledInput();
		setOutputDependencies();
//		cons.addToAlgorithmList(this);
	}
	
	
	public GeoElement[] getOutput() {
		return output;
	}
	
	
	/**
	 * @param i index
	 * @return output geo at position i
	 */
	public GeoElement getOutput(int i) {
		return output[i];
	}
	/**
	 * 
	 * @return number of outputs
	 */
	public int getOutputLength() {
		if (output == null) {
			return 0;
		}

		return output.length;
	}
	
	
	/**
	 * set output number i
	 * 
	 * @param i index
	 * @param geo output geo
	 */
	protected void setOutput(int i, GeoElement geo) {
		output[i] = geo;
	}

	@Override
	final public boolean isIndependent() {
		return false;
	}
	
	final protected void setDependencies() {
		// dependents on input
		for (int i = 0; i < input.length; i++) {
			input[i].addAlgorithm(this);
		}
		doSetDependencies();
	}
	
	abstract protected void setInputOutput();
	
	/**
	 * initialize output list
	 * 
	 * @param g
	 *            only output
	 * 
	 */
	protected void setOutput(GeoElement[] geo) {
		output = geo;
	}

	private void setOutputDependencies() {

		// parent algorithm of output
		for (int i = 0; i < getOutputLength(); i++) {

			setOutputDependencies(getOutput(i));

		}
	}
	
	/**
	 * sets the given geo to be child of this algo
	 * 
	 * @param output
	 */
	protected void setOutputDependencies(GeoElement output) {
		// parent algorithm of output
		output.setParentAlgorithm(this);

		// every algorithm with an image as output
		// should be notified about view changes
		
//		if (output.isGeoImage()) {
//			cons.registerEuclidianViewCE(this);
//		}

		// make sure that every output has same construction as this algorithm
		// this is important for macro constructions that have input geos from
		// outside the macro: the output should be part of the macro
		// construction!
//		if (cons != output.cons) {
//			output.setConstruction(cons);
//		}

	}
	
	/* (non-Javadoc)
	 * @see com.geodroid.common.kernel.geos.ConstructionElement#update()
	 */
	@Override
	public void update() {
//			if (stopUpdateCascade) {
//				return;
//			}

			// update input random numbers without label
//			if (randomUnlabeledInput != null) {
//				for (int i = 0; i < randomUnlabeledInput.length; i++) {
//					randomUnlabeledInput[i].updateRandomGeo();
//				}
//			}

			// counter++;
			// startTime = System.currentTimeMillis();

			// compute output from input
			compute();

			// endTime = System.currentTimeMillis();
			// computeTime += (endTime - startTime);
			// startTime = System.currentTimeMillis();

			// update dependent objects
			for (int i = 0; i < getOutputLength(); i++) {
				getOutput(i).updateCascade();
			}

			// endTime = System.currentTimeMillis();
			// updateTime += (endTime - startTime );
		}

	public boolean hasOutputChangeable() {
		return false;
	}

}
